home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
CUGUK
/
PC_LIBS
/
C045.ZIP
/
CBEAUT.ARC
/
CB.C
next >
Wrap
C/C++ Source or Header
|
1988-09-18
|
41KB
|
1,114 lines
/*===========================================================================
cb.c - C program indenter
Revision History:
08/08/87 Robert B. Sledge (Compuserve 76515,2620):
Obtained cb.c source from C User's Group.
Added extensive comments (there were none).
Changed operation to rename original file to .BAK and
write output to file of original name.
Added support for variable indent_spaces.
Added switches -s, -b, and -l to command line.
Corrected a number of processing bugs.
Compiled with Microsoft C 4.0 compiler.
Added switches to compile under VAX/VMS.
10/30/83 John W. Kindschi Jr.: Modified for Lattice C Ver 1.01
??/??/?? William C. Colley, III: Swiped from CPIG'S UNIX system and
modified to run under BDS C.
Usage: cb [-blis] inputfile [inputfile...]
Switches:
-b Braces indent at level of outside code.
(Default = indent at level of inside code.)
-l Indentation starts at level 1.
(Default = indentation starts at level 0.)
-inn Set number of spaces per indentation level to nn.
(Default = indentation set to 3 spaces per level.)
-s Output written to standard output.
(Default = output to file, rename old .BAK.)
Where inputfile is the file to be pretty printed (the filename may
contain wildcard characters). Under MS-DOS the original file is renamed to
.BAK unless the -s switch is used. Under VAX/VMS a new version of the file
is created.
===========================================================================*/
#include <stdio.h>
#ifndef vms
#include <errno.h> /* for the MSC rename() function */
#endif
#define TEMPNAME "cbtemp.czz" /* temp output file name */
#define SORTOF 2
#define YES 1
#define NO 0
#define BRACES_OUTSIDE 0 /* braces at outside block level */
#define BRACES_INSIDE 1 /* braces at inside block level */
#define START0LEVEL 0 /* indenting starts at level 0 */
#define START1LEVEL 1 /* indenting starts at level 1 */
#define SUCCESS 0 /* return codes for renambak() */
#define FAILURE1 -1
#define FAILURE2 -2
#define MAXBRACE 20 /* max nested brace level allowed */
#define MAXIF 10 /* max nested 'if' level allowed */
#define MAXLEVEL 10 /* max number of braced blocks preceeded by
* non-braced block statements */
int swflg = NO; /* processing 'switch' flag */
int sswflg[MAXBRACE]; /* saved 'swflg's */
int aflg[MAXLEVEL]; /* YES/NO flag (has to do with braces???) */
int saflg[MAXBRACE][MAXIF]; /* saved aflg[] */
int nblk[MAXLEVEL]; /* non-braced blocks at current 'level' */
int snblk[MAXBRACE][MAXIF]; /* saved nblks[] */
int brclev = 0; /* brace {} level: increments on '{'
* and decrements on '}' */
int sbrclev[MAXLEVEL]; /* saved 'brclev's */
int iflev = 0; /* 'if' level */
int siflev[MAXBRACE]; /* saved 'iflev's */
int ifflg = -1; /* processing 'if' flag */
int sifflg[MAXBRACE]; /* saved 'ifflg's */
int tabs = 0; /* current level of indentation */
int stabs[MAXBRACE][MAXIF]; /* saved 'tabs' */
int level = 0; /* brace level after non-braced block stmt */
int addflg = NO; /* add-extra-indent flag */
int elseflg = NO; /* processing 'else' flag */
int qflg = NO; /* question mark flag */
int solflg = YES; /* start-of-line flag */
int stdoutflg = NO; /* flag to use stdout for output */
int tabsflg = START0LEVEL; /* indenting starts at level 0 */
int paren = 0; /* 'parenthesis' level */
int peek = -1; /* peekahead character */
int j = 0; /* char index for output buffer */
int nindent = 3; /* number of spaces per indent level */
int braces = BRACES_INSIDE; /* braces indent at inside block level */
FILE *inpfile, *outfile; /* input and output file pointers */
static char string[200]; /* output string buffer */
char *wif[2] = { "if", NULL };
char *welse[2] = { "else", NULL };
char *wfor[2] = { "for", NULL };
char *wcase[3] = { "case", "default", NULL };
char *wswitch[2]= { "switch", NULL };
char lchar; /* last non-whitespace && non-comma char written to output */
char pchar; /* previous non-whitespace char from input stream */
int lastchar; /* last character received */
int c; /* character buffer */
char cc; /* character buffer */
main( argc, argv)
int argc;
char **argv;
{
void cb(); /* main processing function */
char *findfile(); /* vms wildcard processing routine */
int n; /* loop index variable */
char *arg; /* ptr to command line character */
char *ptr; /* ptr to filename string */
/* show the correct usage of this utility */
if (argc <= 1)
{
fprintf(stderr, "V2.1 Usage: cb [-blis] inputfile [inputfile...]\n");
fprintf(stderr, " Switches:\n\n");
fprintf(stderr, " -b Braces indent at level of outside code.\n");
fprintf(stderr, " (Default = indent at level of inside code.)\n");
fprintf(stderr, " -l Indentation starts at level 1.\n");
fprintf(stderr, " (Default = indentation starts at level 0.)\n");
fprintf(stderr, " -inn Set number of spaces per indentation level to nn.\n");
fprintf(stderr, " (Default = indentation set to 3 spaces per level.)\n");
fprintf(stderr, " -s Output written to standard output.\n");
#ifdef vms
fprintf(stderr, " (Default = Create a new version of the file.)\n");
#else
fprintf(stderr, " (Default = output to file, rename old .BAK.)\n");
#endif
return;
}
/* process command line tokens */
while( --argc > 0)
{
/* process a command line switch */
arg = *++argv;
if ( *arg == '-')
{
/* handle multiple switches behind a single '-' */
while( *++arg != '\0')
switch (*arg)
{
default:
fprintf(stderr, "Unknown Switch (-%c)... Ignored!!\n", *arg);
break;
case 'b':
case 'B':
braces = BRACES_OUTSIDE; /* braces at outside code level */
break;
case 'i':
case 'I':
if ((n=atoi(++arg)) > 0)
nindent = n; /* set spaces per indent */
/* skip over the digits in the number */
while (*(arg+1) >= '0' && *(arg+1) <= '9')
arg++;
break;
case 'l':
case 'L':
tabsflg = START1LEVEL; /* indentation starts at level 1 */
break;
case 's':
case 'S':
stdoutflg = YES; /* output goes to standard out */
break;
} /* end switch() */
}
/* not a command line switch: process as a filename */
else
{
#ifdef vms
/* findfile() returns ptr to matching (possibly wildcard) file specs.
* this is where we handle wildcards for vms */
while ( (ptr=findfile(arg)) != NULL)
cb( ptr); /* process the filename ptd to by 'ptr' */
#else
cb( arg); /* process the filename ptd to by 'arg' */
#endif
}
} /* end while() to process command line tokens */
} /*----------------------------- main() --------------------------------*/
/*-----------------------------------------------------------------------*
* cb() - beautify the specified file
*
* Synopsis:
* cb( filename)
* char *filename; ptr to name of file to process
*
* Returns: void
*-----------------------------------------------------------------------*/
void cb( filename)
char *filename; /* ptr to name of file to process */
{
int ct;
int i,n; /* temp variables */
/* open the input file */
if ( (inpfile = fopen(filename,"r")) == NULL)
{
fprintf(stderr, "\nFile (%s) not found.\n\n", filename);
return;
}
/* open the output stream */
if (stdoutflg == NO)
{
#ifdef vms
/* remove explicit version number so file defaults to next higher version */
for( n = strlen(filename); n >= 0; n--)
if (filename[n] == ';')
filename[n] = '\0';
if ((outfile = fopen(filename,"w")) == NULL)
{
fprintf( stderr, "Couldn't create output file (%s).\n", filename);
return;
}
#else /* non-vms */
if ((outfile = fopen(TEMPNAME,"w")) == NULL)
{
fprintf( stderr, "Couldn't create output file (%s).\n", filename);
return;
}
#endif
}
/* open the output stream to stdout */
else
outfile = stdout;
/* initialize parameters */
cbinit();
/* process the characters from the input file and send to output stream */
while ( (c=getchr()) != EOF)
{
switch(c) /* switch on input character */
{
/* not a special character: just pack it into output string */
default:
string[j++] = c;
if (c != ',')
lchar = c; /* remember last character */
break;
/* handle a whitespace character */
case ' ':
case '\t':
if (lookup(welse) == YES) /* processing an 'else' */
{
elseflg = SORTOF; /* remember the 'else' statement */
gotelse(); /* adjust for the 'else' */
/* not start-of-line or characters in output buffer */
if( solflg == NO || j > 0)
string[j++] = c; /* copy whitespace to output buf */
putb(); /* write output buffer */
solflg = NO; /* not start-of-line */
break; /* loop back around */
}
/* not start-of-line or chars in buffer */
if (solflg == NO || j > 0)
string[j++] = c; /* copy whitespace to output buf */
break; /* loop back around */
/* handle a newline character */
case '\n':
/* Check for processing an 'else' statement.
* Elseflg may have been set previously by the ' ' or '\t' special
* character case statement, in which case gotelse() has already
* been called and we don't want to call it again here. Note that
* we won't detect the else here in that case since putb() has
* been called and flushed the 'else' to the output stream. In order
* to help us here we set elseflg=SORTOF back there so we can go ahead
* and appropriately handle the 'else' here.
*/
if (elseflg != SORTOF && (elseflg=lookup(welse)) == YES)
gotelse(); /* adjust for this 'else' stmt */
putb(); /* write output buffer */
fprintf( outfile, "\n"); /* write newline to output stream */
solflg = YES; /* start-of-line is true */
/* we are processing an 'else' */
if (elseflg == YES || elseflg == SORTOF)
{
nblk[level]++; /* increment non-braced block count */
tabs++; /* stuff after 'else' is indented */
elseflg = NO; /* reset the flag */
}
/* somewhere inside parenthesis: add an extra temp indent */
else if( paren > 0)
addflg = YES;
break; /* loop back around */
/* handle a left brace */
case '{':
if (lookup(welse) == YES) /* processing an 'else' */
gotelse();
siflev[brclev] = iflev; /* save 'if' level */
sifflg[brclev] = ifflg; /* save 'if' flag */
iflev = 0; /* current 0 at new brace level */
ifflg = NO; /* no 'if's yet at new brace level */
sswflg[brclev] = swflg; /* save 'switch' flag */
if (++brclev > MAXBRACE) /* increment brace level */
{
fprintf(stderr,"Too many nested braces in (%s), aborting!!\n",
filename);
goto END;
}
/* start-of-line and non-braced block statements above us */
if (solflg == YES && nblk[level] > 0)
{
nblk[level]--; /* decrement since we now have a brace */
tabs--; /* and it will indent things for us */
}
string[j++] = c; /* store '{' in output buffer */
/* braces at inside block level (never for switch stmt) */
if (swflg == NO && braces == BRACES_INSIDE)
tabs++; /* indent right one level */
putb(); /* write buffer to output stream */
getnl(); /* get remaining whitespace & comments */
putb(); /* write buffer to output stream */
fprintf( outfile, "\n"); /* write newline to output stream */
solflg = YES; /* start-of-line is true */
/* braces at outside block level (always for switch stmt) */
if (swflg == YES || braces == BRACES_OUTSIDE)
tabs++; /* indent right one level */
swflg = NO; /* no 'switch's yet at this level */
/* some non-braced block statements above us at this 'level' */
if (nblk[level] > 0)
{
aflg[level] = YES; /* set flag true */
/* start new brace level following some non-braced block stmts */
if (++level > MAXLEVEL)
{
fprintf(stderr,"Too many nested braces in (%s), aborting!!\n",
filename);
goto END;
}
sbrclev[level] = brclev; /* save the brace level */
}
break; /* loop back around */
/* handle a right brace */
case '}':
brclev--; /* decrement the brace level */
if ((iflev = siflev[brclev]-1) < 0)
iflev = 0;
ifflg = sifflg[brclev]; /* restore 'if' flag at level */
swflg = sswflg[brclev]; /* restore 'switch' flag */
putb(); /* write output buffer */
/* braces at outside block level (always for switch stmt) */
if (swflg == YES || braces == BRACES_OUTSIDE)
tabs--; /* indent left one level */
ptabs(); /* output leading indentation */
/* braces at inside block level (never for switch stmt) */
if (swflg == NO && braces == BRACES_INSIDE)
tabs--; /* indent left one level */
swflg = sswflg[brclev] = NO; /* no 'switch' stmt at this point */
/* peek at next character, it is a semicolon ';' */
if ((peek = getchr()) == ';')
{
fprintf(outfile, "%c;", c); /* output the "};" to buffer */
peek = -1; /* forget the ';' */
}
/* next character is not a semicolon ';' */
else
fprintf( outfile, "%c", c); /* output the '}' to buffer */
getnl(); /* get remaining whitespace & comments */
putb(); /* write output buffer */
fprintf( outfile, "\n"); /* write newline to output stream */
solflg = YES; /* start-of-line is true */
/* conditions are right to decrement non-blocked brace level */
if (brclev < sbrclev[level])
if (level > 0)
level--; /* decrement non-blocked brace level */
/* leaving a braced block preceeded by non-braced block stmts */
/* adjust things accordingly */
if (aflg[level] > 0)
{
tabs -= nblk[level]; /* indent left appropriate number */
nblk[level] = 0; /* no non-braced blocks at 'level' now */
aflg[level] = NO; /* reset the aflg[] flag */
}
break; /* loop back around */
/* handle a single quote or double quote */
case '"':
case '\'':
string[j++] = c; /* copy quote to output buffer */
/* copy characters within quotes to output buffer */
while ( (cc=getchr()) != c)
{
string[j++] = cc; /* copy char to output buffer */
if( cc == '\\') /* copy an escaped character */
string[j++] = getchr(); /* straight into output buffer */
if (cc == '\n') /* we have a newline */
{
putb(); /* write output buffer */
solflg = YES; /* start-of-line is true */
}
}
string[j++] = cc; /* copy last char to output buffer */
/* get remaining whitespace & comments: we hit a newline */
if (getnl() == YES)
{
lchar = cc; /* remember last character */
peek = '\n'; /* remember the newline */
}
break; /* loop back around */
/* handle a semicolon */
case ';':
string[j++] = c;
putb();
/* leaving one or more non-braced block statements */
if (nblk[level] > 0 && aflg[level] == NO)
{
tabs -= nblk[level]; /* indent left an appropriate amount */
nblk[level] = 0; /* no non-braced blocks at 'level' now */
}
getnl(); /* get remaining whitespace & comments */
putb(); /* write the output buffer */
fprintf( outfile, "\n"); /* write a newline to output stream */
solflg = YES; /* start-of-line is true */
/* we are in one or more nested 'if' statements */
if (iflev > 0)
/* we are currently processing an 'if' statement */
if (ifflg == YES)
{
iflev--; /* decrement 'if' level */
ifflg = NO; /* and reset the 'if' flag */
}
/* not currently processing an 'if' statement */
else
iflev = 0; /* not in nested 'if' stmts any more */
break;
/* handle an escaped character; copy both to output string */
case '\\':
string[j++] = c; /* copy the '\' */
string[j++] = getchr(); /* copy the character */
break;
/* handle a question mark; it may be a conditional operator (?:) */
case '?':
qflg = YES; /* remember the '?' */
string[j++] = c; /* copy to output string */
break;
/* handle a colon */
case ':':
string[j++] = c; /* copy to output string */
/* we are processing a conditional operator (?:) */
if (qflg == YES)
{ /* no further processing needed */
qflg = NO; /* just cancel the flag */
break; /* and loop back around */
}
/* processing 'case' or 'default' */
if (lookup(wcase) == YES)
{
tabs--; /* indent left */
putb(); /* write the "case:" or "default:" */
tabs++; /* indent right */
}
/* not conditional operator (?:) or case: or default: */
else
{
solflg = NO; /* start-of-line is false */
putb(); /* write the output buffer */
}
/* if next character is a semicolon */
if ((peek = getchr()) == ';')
{
fprintf( outfile, ";"); /* then output the ';' */
peek = -1; /* don't remember the peek */
}
getnl(); /* get remaining whitespace and comments */
putb(); /* write the output buffer */
fprintf( outfile, "\n"); /* write a newline to output stream */
solflg = YES; /* start-of-line is true */
break; /* loop back around */
/* handle a slash */
case '/':
string[j++] = c; /* copy to output buffer */
if ( (peek=getchr()) != '*') /* next char is not a '*' */
break; /* loop back around */
string[j++] = peek; /* copy '*' to output buffer */
peek = -1; /* forget the peek */
comment(); /* handle rest of the comment */
break; /* loop back around */
/* handle a left parenthesis */
case '(':
string[j++] = c; /* copy '(' to the output buffer */
paren++; /* increment paren level */
/* processing 'for' statement */
if (lookup(wfor) == YES)
{
/* gobble till we process a semicolon */
while( (c=cgets()) != ';')
;
ct = 0; /* no nesting yet */
cont:
/* gobble till we process a right paren */
while ( (c=cgets()) != ')')
{
if (c == '(') /* we hit a left paren */
ct++; /* increment nesting level */
}
/* we are still nested: keep gobbling */
if (ct != 0)
{
ct--; /* decrease nesting level */
goto cont; /* and continue gobbling till */
} /* we find the right paren */
paren--; /* decrement paren level */
putb(); /* put the output line out */
/* output whitespace and comments: handle multi-line 'for' */
if (getnl() == YES) /* we got to a newline */
{
peek = '\n'; /* remember the newlne */
nblk[level]++; /* increment non-braced block level */
tabs++; /* indent right */
aflg[level] = NO; /* reset the flag */
}
break; /* loop back around */
} /* end 'for' processing */
/* processing an 'if' statement */
if (lookup(wif) == YES)
{
putb(); /* write output buffer */
stabs[brclev][iflev] = tabs; /* save current state */
snblk[brclev][iflev] = nblk[level];
saflg[brclev][iflev] = aflg[level];
if (++iflev > MAXIF) /* increment the 'if' level */
{
fprintf(stderr,"Too many nested 'if's in (%s), aborting!!\n",
filename);
goto END;
}
ifflg = YES; /* show that we are doing an 'if' stmt */
} /* end 'if' processing */
/* processing a 'switch' statement: set the flag */
if (lookup(wswitch) == YES)
swflg = YES; /* show that we're in 'switch' stmt */
break; /* loop back around */
/* handle a right parenthesis */
case ')':
paren--; /* decrement paren level */
string[j++] = c; /* copy ')' to output buffer */
putb(); /* write output buffer */
/* get remaining whitespace and comments: we hit a newline */
if (getnl() == YES)
{
peek = '\n'; /* remember the newline we hit */
if (paren != 0) /* we are inside parens */
addflg = YES; /* add-extra-indent is true */
/* This is the where block statements that are terminated
* by a right parenthesis receive their indentation. */
else if (tabs > 0) /* we are indented */
{
nblk[level]++; /* increment non-braced block level */
tabs++; /* indent right one level */
aflg[level] = NO; /* reset the flag */
/* If processing an 'else if(...)' (i.e. elseflg == SORTOF)
* we don't want to indent again later so turn elseflg OFF.
*/
if (elseflg == SORTOF)
elseflg = NO;
}
}
break; /* loop back around */
/* handle a '#' character (preprocessor directive) */
case '#':
string[j++] = c; /* copy to output buffer */
while ( (cc=getchr()) != '\n') /* copy up to newline */
string[j++] = cc;
string[j++] = cc; /* copy the newline to buffer */
solflg = NO; /* start-of-line is false */
putb(); /* write output buffer */
solflg = YES; /* start-of-line is true */
break; /* loop back around */
} /* switch(c) */
} /* while ( (c = getchar()) != EOF) */
END:
fclose( inpfile); /* close the input file */
#ifdef vms
if (stdoutflg == NO)
fclose( outfile); /* close the output file */
#else /* non-vms */
/* MS-DOS: rename the original file to .BAK and rename new file */
if (stdoutflg == NO)
{
fclose( outfile); /* close the output file */
if ( renambak(filename) != SUCCESS)
{
fprintf( stderr, "Cannot rename (%s) to .BAK; Output = (%s)\n",
filename, TEMPNAME);
exit();
}
if (rename(TEMPNAME,filename) != SUCCESS)
{
fprintf( stderr, "Cannot rename temporary file; Output = (%s)\n",
TEMPNAME);
exit();
}
}
#endif /* vms */
} /*---------------------------- cb() ------------------------------*/
/* cbinit() - initialize the beautifier variables
*
*/
cbinit()
{
register i, j;
for (i = 0; i < MAXLEVEL; i++)
{
aflg[i] = 0; /* YES/NO flag (has to do with braces) */
nblk[i] = 0; /* non-braced blocks at current 'level' */
sbrclev[i] = 0; /* saved 'brclev's */
}
for (i = 0; i < MAXBRACE; i++)
{
sifflg[i] = 0; /* saved 'ifflg's */
siflev[i] = 0; /* saved 'iflev's */
sswflg[i] = 0; /* saved 'swflg's */
for (j = 0; j < MAXIF; j++)
{
saflg[i][j] = 0; /* saved aflg[] */
snblk[i][j] = 0; /* saved nblks[] */
stabs[i][j] = 0; /* saved 'tabs' */
}
}
brclev = 0; /* brace {} level: increments on '{'
* and decrements on '}' */
iflev = 0; /* 'if' level */
ifflg = -1; /* processing 'if' flag */
tabs = 0; /* current level of indentation */
level = 0; /* brace level after non-braced block stmt */
addflg = NO; /* add-extra-indent flag */
elseflg = NO; /* processing 'else' flag */
qflg = NO; /* question mark flag */
solflg = YES; /* start-of-line flag */
swflg = NO; /* processing 'switch' flag */
paren = 0; /* 'parenthesis' level */
peek = -1; /* peekahead character */
j = 0; /* char index for output buffer */
} /*---------------------------- cbinit() ---------------------------*/
/* ptabs() - put out leading white space for proper indentation
*
* Returns: nothing
*/
ptabs()
{
register i;
/* don't output any leading whitespace unless we are at start-of-line */
if (solflg == NO)
return;
/* if indenting starts at the left column */
if (tabsflg == START0LEVEL)
i = (tabs-1) * nindent;
/* otherwise indenting starts at the first level */
else
i = tabs * nindent;
/* print leading \t's where possible */
for ( ; i >= 8; i -= 8)
fprintf( outfile, "\t");
/* finish up with spaces */
for ( ; i > 0; i--)
fprintf( outfile, " ");
} /*--------------------------- ptabs() ----------------------------*/
/* getchr() - get character from input file
*
* Sets: lastchar to the character gotten from the input file
*
* Returns:
* peek if peek contained a lookahead character
* getc(inpfile) otherwise
*/
getchr()
{
/* no lookahead char and lastchar not whitespace */
if (peek < 0 && lastchar != ' ' && lastchar != '\t')
pchar = lastchar;
/* get the current 'last character' */
lastchar = (peek < 0) ? getc(inpfile) : peek;
peek = -1;
return( lastchar == '\r' ? getchr() : lastchar);
} /*------------------------- getchr() ----------------------------*/
/* putb() - put the output buffer to the output stream
*
*/
putb()
{
/* output buffer contains some characters */
if (j > 0)
{
/* we are at the start of a line */
if (solflg == YES)
{
if (addflg == YES) /* we are to add an extra indent */
{
if (tabs > 0) /* if things are currently indented */
tabs++; /* then temporarily add more indent */
ptabs(); /* and output leading white space */
tabs--; /* then restore normal indent level */
addflg = NO; /* and turn the flag off */
}
else
ptabs(); /* output leading white space */
solflg = NO; /* start-of-line is false now */
}
string[j] = '\0'; /* terminate output buffer with null */
fprintf( outfile, "%s", string); /* write buffer to output stream */
j = 0; /* mark output buffer as empty now */
}
/* output buffer is empty */
else
{
if (solflg == YES) /* at start-of-line */
addflg = NO; /* add-extra-indent is false */
}
} /*--------------------------- putb() -----------------------------*/
/* lookup() - see if string in 'table' is contained in output buffer
*
*/
lookup( table)
char *table[];
{
char r;
int i,kk,k,l;
/* output buffer is empty, can't match that */
if (j < 1)
return(NO);
/* otherwise nul terminate the output buffer */
else
string[j] = '\0';
/* skip leading spaces in output buffer */
kk = 0;
while (string[kk] == ' ')
kk++;
/* search the entries in the table until a NULL is found */
for (i = 0; table[i] != NULL; i++)
{
l = 0;
for( k=kk; (r = table[i][l++]) == string[k] && r != '\0'; k++)
;
if (r == '\0' && (string[k] < 'a' || string[k] > 'z'))
return( YES); /* match found */
}
return( NO); /* no match found */
} /*-------------------------- lookup() ---------------------------*/
/* cgets() - copy escaped chars and quoted strings to output
*
* Returns: last start of sequence character
*/
cgets()
{
char ch; /* char that starts the current sequence */
beg:
/* copy an escaped character to the output */
if ((ch = string[j++] = getchr()) == '\\')
{
string[j++] = getchr();
goto beg;
}
/* character is ' or " */
if (ch == '\'' || ch == '"')
{
/* copy until we hit the terminating ' or " */
while((cc = string[j++] = getchr()) != ch)
if (cc == '\\') /* copy escaped characters */
string[j++] = getchr(); /* unscathed */
goto beg;
}
/* if start of char sequence is a newline */
if (ch == '\n')
{
putb(); /* write the output buffer */
solflg = YES; /* start-of-line is true */
addflg = YES; /* add-extra-indent is true */
goto beg; /* and start all over again */
}
else
return( ch); /* otherwise return start of sequence */
} /*-------------------------- cgets() -----------------------------*/
/* gotelse() - handle processing after an 'else' is discovered
*
* Returns: nothing
*/
gotelse()
{
tabs = stabs[brclev][iflev]; /* return to previous tab level */
nblk[level] = snblk[brclev][iflev]; /* return to previous nblk level*/
aflg[level] = saflg[brclev][iflev]; /* return to previous aflg flag */
ifflg = YES; /* show that we are doing an 'if' stmt */
} /*------------------------- gotelse() ---------------------------*/
/* getnl() - get remaining white space and comments
*
* Return:
* 1 YES if we got to a '\n'
* 0 NO if we did not get to a '\n'
*/
getnl()
{
/* copy white space to output */
while ((peek = getchr()) == '\t' || peek == ' ')
{
string[j++] = peek;
peek = -1;
}
/* we may have a comment to gobble up */
if ((peek = getchr()) == '/')
{
peek = -1; /* don't remember the '/' */
/* its a comment: copy it to the output */
if ((peek = getchr()) == '*')
{
string[j++] = '/'; /* copy comment start to output */
string[j++] = '*';
peek = -1; /* don't remember the peek */
comment(); /* copy rest of comment to output */
}
/* its not a comment: copy the '/' to the output */
else
string[j++] = '/';
}
/* return YES is we have gotten to the newline */
if ((peek = getchr()) == '\n')
{
peek = -1; /* don't remember the peek */
return( YES);
}
return( NO); /* did not find the newline */
} /*--------------------------- getnl() ----------------------------*/
/* comment() - copy remainder of a comment to the output
*
* Description:
*
* At this point the leading '/*' of the comment have been placed
* into the output buffer. This routine copies the remainder of the
* comment (even across multiple lines) to the output stream
*
* Returns: nothing
*/
comment()
{
int temp = tabs; /* temp tabs storage */
int multiline = NO; /* multiline comment flag */
string[j] = '\0'; /* nul terminate output buffer */
/* process characters inside the comment */
while ( (c = string[j++] = getchr()) != EOF )
{
/* reached the end-of-comment */
if ( j > 1 && string[j-2] == '*' && c == '/')
break;
/* hit a newline: flush buffer to output and handle multiline comment */
if (c == '\n')
{
multiline = YES; /* set multiline flag */
putb(); /* write output buffer */
string[j] = '\0'; /* nul terminate output string */
solflg = YES; /* start-of-line is true */
tabs = 0; /* don't auto-indent next comment lines */
}
}
/* doing a multiline comment and last line terminated with newline */
/* make sure we output the buffer before restoring the normal 'tabs' */
if (multiline == YES && getnl() == YES)
{
string[j++] = '\n'; /* put newline into output buffer */
putb(); /* and flush buffer to output */
solflg = YES; /* start-of-line is true */
}
tabs = temp; /* restore tabs */
} /*-------------------------- comment() ---------------------------*/
#ifndef vms
/*--------------------------------------------------------------------
* renambak() - rename filename to .BAK
*
* Revision History:
* 08/08/87 Robert B. Sledge Initial Creation.
*
* Synopsis:
* renambak( filename)
* char *filename; ptr to file to be renamed to .BAK
*
* Description:
* Check that the 'filename' exists, if not then return FAILURE1.
* A copy of the 'filename' string will have its existing file type
* stripped and .BAK appended in its place. Then the file will be
* renamed to .BAK. If this fails due to a previously existing .BAK
* file then the existing .BAK file will be deleted and the rename
* will be retried. If this attempt fails then return FAILURE1 for
* lack of anything more descriptive.
*
* Returns:
* 0 = SUCCESS
* -1 = FAILURE1: Input File Does Not Exist
* -2 = FAILURE2: Out of Memory
*
* Cautions: Specific to Microsoft C (MS-DOS)
*/
int renambak( filename)
char *filename; /* ptr to filename string to rename */
{
int status = SUCCESS; /* return status */
char *malloc(); /* memory allocation function */
char *strchr(); /* character search function */
char *bakfile; /* ptr to .BAK filename */
char *p; /* ptr to '.' in filename */
FILE *stream; /* stream pointer */
/* check that the input file exists */
if ( (stream=fopen(filename,"r")) == NULL)
return( FAILURE1);
fclose( stream); /* close the opened stream */
/* create a temporary copy of the filename */
if ( (bakfile=malloc(strlen(filename)+6)) == NULL)
return( FAILURE2);
strcpy( bakfile, filename); /* copy 'filename' to 'bakfile' */
/* create the .BAK file name string */
if ( (p=strchr(bakfile,'.')) != NULL) /* ptr to '.' in the string */
*p = '\0'; /* terminate string at the "." */
strcat( bakfile, ".BAK"); /* and add .BAK to the end of the string */
/* rename existing file to .BAK */
if ( rename(filename,bakfile) != SUCCESS)
{ /* another .BAK file is in the way */
unlink( bakfile); /* try deleting an existing .BAK file */
if ( rename(filename,bakfile) != SUCCESS)
status = FAILURE1; /* looks like its just not our day */
}
free( bakfile); /* free malloc'ed memory */
return( status); /* and return our status */
} /*--------------------------- renambak() ----------------------------*/
#endif /* ifndef vms */
#ifdef vms
/* findfile.c - return all filespecs that match the wildcard filespec
*
* Edit History:
* 03/02/87 RBS Initial Creation.
*
* Synopsis:
* char *findfile( filespec)
* char *filespec Pointer to string containing wildcard filespec
*
* Description: The file specification (possibly containing wildcards) is
* passed by pointer "filespec". A pointer to the first matching file
* specification will be returned. Successive calls to findfile() with the
* same "filespec" will return successive matching file specs. When no more
* matching files are found a NULL will be returned. If the "filespec" is
* changed before all matching files have been returned the routine will
* start a new file context (effectively erasing the list of remaining files
* for the previous context).
*
* Returns: Pointer to a matching filespec, NULL if no more files match or
* an error condition occurs.
*
* Cautions: This routine is specific to VAX/VMS.
*/
#include <descrip.h> /* for string descriptor definitions */
#include <ssdef.h> /* defs for system services return values */
#include <rms.h> /* def for RMS$_NORMAL */
#define MATCH 0 /* strcmp() returns for equal strings */
char *findfile( filespec)
char *filespec; /* Ptr to string containing wildcard filespec */
{
/* local variables */
struct dsc$descriptor_s ifile; /* input file string descriptor structure */
struct dsc$descriptor_s rfile; /* result file string descriptor structure */
static char inpfile[256]; /* storage for the input file specification */
static struct /* varying string storage structure */
{
unsigned short curlen; /* current length of varying string */
char body[256]; /* body of varying string */
} vs;
int status; /* return status from LIB$FIND_FILE */
static unsigned context=0; /* used by LIB$FIND_FILE to save file context */
/* this is a new input file spec: initialize things */
if ( strcmp(filespec,inpfile) != MATCH)
{
strcpy( inpfile, filespec); /* copy filespec to static string */
/* there is a current file context: end it since we are starting fresh */
if (context != 0)
LIB$FIND_FILE_END( &context); /* end previous context */
}
/* setup the descriptor for the input (wildcard) filespec string */
ifile.dsc$w_length = strlen(inpfile); /* string length */
ifile.dsc$a_pointer = inpfile; /* pointer to string */
ifile.dsc$b_class = DSC$K_CLASS_S; /* fixed-length descriptor class */
ifile.dsc$b_dtype = DSC$K_DTYPE_T; /* ASCII string type */
/* setup the descriptor for the output (matching) filespec string */
rfile.dsc$w_length = 255; /* maximum filename length */
rfile.dsc$a_pointer = &vs; /* ptr to string structure */
rfile.dsc$b_class = DSC$K_CLASS_VS; /* varying string class */
rfile.dsc$b_dtype = DSC$K_DTYPE_VT; /* varying string type */
vs.curlen = 0; /* no matching string yet */
/* parse the component item from the file specification */
status = LIB$FIND_FILE( &ifile, &rfile, &context, 0, 0, 0, 0);
vs.body[vs.curlen] = '\0'; /* null terminate the string */
#ifdef DEBUG
printf("LIB$FIND = %X, file = %.255s\n", status, vs.body);
#endif
if (status == RMS$_NORMAL)
return(vs.body);
else
return(NULL);
} /*-------------------------- findfile() -------------------------*/
#endif /* ifdef vms */